using System;
using System.Collections.Generic;
using LS.UnityExtensions;

namespace LS.Digitize
{
    public class ArraySerializer: CollectionSerializer
    {
        public ArraySerializer(Type type, Type elementType) : base(type, elementType)
        {
        }

        public override void Write(IWriter writer, object obj)
        {
            ISerializer elementSerializer = ElementSerializer;
            if (obj == null)
            {
                writer.WriteNull();
                return;
            };

            var array = (System.Array)obj;
            
            if(elementSerializer == null)
                throw new ArgumentNullException("Serializer argument cannot be null.");

            for(int i=0; i<array.Length; i++)
            {
                using (writer.WriteCollectionItemScope(i))
                {
                    elementSerializer.Write(writer, array.GetValue(i));
                }
            }
        }

        public override object Read(IReader reader)
        {
            ISerializer elementSerializer = ElementSerializer;
            var list = new List<object>();
            if (!ReadICollection(reader, list, elementSerializer, out bool nullCollection))
            {
                if (nullCollection)
                    return null;
                else
                    return LSReflection.ArrayCreateInstance(elementSerializer.DataType, 0);
            }

            var array = LSReflection.ArrayCreateInstance(elementSerializer.DataType, list.Count);
            int i = 0;
            foreach (var item in list)
            {
                array.SetValue(item, i);
                i++;
            }

            return array;
        }

        public override void ReadInto(IReader reader, ref object obj)
        {
            throw new NotImplementedException();
        }
    }
    
    public class ArraySerializer<T>: CollectionSerializer<T[], T>
    {
        public ArraySerializer() : base()
        {
        }

        public override void ReadInto(IReader reader, ref object obj)
        {
            throw new NotImplementedException();
        }

        public override void WriteData(IWriter writer, T[] obj)
        {
            ISerializer elementSerializer = ElementSerializer;
            if (obj == null)
            {
                writer.WriteNull();
                return;
            };

            T[] array = obj;
            
            if(elementSerializer == null)
                throw new ArgumentNullException("Serializer argument cannot be null.");

            using (writer.WriteCollectionScope())
            {
                for (int i = 0; i < array.Length; i++)
                {
                    using (writer.WriteCollectionItemScope(i))
                        elementSerializer.Write(writer, array[i]);
                }
            }
        }

        public override T[] ReadData(IReader reader)
        {
            ISerializer elementSerializer = ElementSerializer;
            var list = new List<T>();
            
            if (!ReadICollection(reader, list, elementSerializer, out bool nullCollection))
            {
                if (nullCollection) return null;
                return Array.Empty<T>();
            }
            
            return list.ToArray();
        }
    }
}